﻿using System;
using System.Collections.Generic;

namespace Dexter.Caching {
	/// <summary>
	/// The base contract for cache provider implementation.
	/// </summary>
	public interface ICacheProvider {
		/// <summary>
		/// Adds new object into the cache repository
		/// </summary>
		/// <param name="key">The cache key.</param>
		/// <param name="value">The object to add.</param>
		/// <param name="timeout">The timeout of the cache object.</param>
		/// <remarks>
		///		If the object will never expire, use <see cref="TimeSpan.Zero"/>
		/// </remarks>
		/// <exception cref="ArgumentException">Will be throw if <paramref name="key"/> is empty.</exception>
		/// <exception cref="ArgumentNullException">Will be throw if <paramref name="key"/> is null.</exception>
		void Add ( string key , object value , TimeSpan timeout );

		/// <summary>
		/// Adds new object into the cache repository
		/// </summary>
		/// <param name="key">The cache key.</param>
		/// <param name="value">The object to add.</param>
		/// <param name="timeout">The timeout of the cache object.</param>
		/// <param name="tags">The tags of the object (it cloud be used for search).</param>
		/// <remarks>
		/// If the object will never expire, use <see cref="TimeSpan.Zero"/>
		/// </remarks>
		/// <exception cref="ArgumentException">Will be throw if <paramref name="key"/> is empty.</exception>
		/// <exception cref="ArgumentNullException">Will be throw if <paramref name="key"/> is null.</exception>
		void Add ( string key , object value , TimeSpan timeout , string[] tags );

		/// <summary>
		/// Adds new object into the cache repository
		/// </summary>
		/// <param name="key">The cache key.</param>
		/// <param name="value">The object to add.</param>
		/// <param name="timeout">The timeout of the cache object.</param>
		/// <param name="region">The region name.</param>
		/// <param name="tags">The tags of the object (it cloud be used for search).</param>
		/// <remarks>
		/// If the object will never expire, use <see cref="TimeSpan.Zero"/>
		/// </remarks>
		/// <exception cref="ArgumentException">Will be throw if <paramref name="key"/> is empty.</exception>
		/// <exception cref="ArgumentNullException">Will be throw if <paramref name="key"/> is null.</exception>
		/// <exception cref="ArgumentException">Will be throw if <paramref name="region"/> is empty.</exception>
		/// <exception cref="ArgumentNullException">Will be throw if <paramref name="region"/> is null.</exception>
		void Add ( string key , object value , TimeSpan timeout , string region , string[] tags );

		/// <summary>
		/// If the specified object doesn't exist into the repository, it will be added. Otherwise it will update the existing object.
		/// </summary>
		/// <param name="key">The cache key.</param>
		/// <param name="value">The object to add.</param>
		/// <param name="timeout">The timeout of the cache object.</param>
		/// <remarks>
		///		If the object will never expire, use <see cref="TimeSpan.Zero"/>
		/// </remarks>
		/// <exception cref="ArgumentException">Will be throw if <paramref name="key"/> is empty.</exception>
		/// <exception cref="ArgumentNullException">Will be throw if <paramref name="key"/> is null.</exception>
		void Put ( string key , object value , TimeSpan timeout );
		
		/// <summary>
		/// If the specified object doesn't exist into the repository, it will be added. Otherwise it will update the existing object.
		/// </summary>
		/// <param name="key">The cache key.</param>
		/// <param name="value">The object to add.</param>
		/// <param name="timeout">The timeout of the cache object.</param>
		/// <param name="tags">The tags of the object (it cloud be used for search).</param>
		/// <remarks>
		/// If the object will never expire, use <see cref="TimeSpan.Zero"/>
		/// </remarks>
		/// <exception cref="ArgumentException">Will be throw if <paramref name="key"/> is empty.</exception>
		/// <exception cref="ArgumentNullException">Will be throw if <paramref name="key"/> is null.</exception>
		void Put ( string key , object value , TimeSpan timeout , string[] tags );
		
		/// <summary>
		/// If the specified object doesn't exist into the repository, it will be added. Otherwise it will update the existing object.
		/// </summary>
		/// <param name="key">The cache key.</param>
		/// <param name="value">The object to add.</param>
		/// <param name="timeout">The timeout of the cache object.</param>
		/// <param name="region">The region name.</param>
		/// <param name="tags">The tags of the object (it cloud be used for search).</param>
		/// <remarks>
		/// If the object will never expire, use <see cref="TimeSpan.Zero"/>
		/// </remarks>
		/// <exception cref="ArgumentException">Will be throw if <paramref name="key"/> is empty.</exception>
		/// <exception cref="ArgumentNullException">Will be throw if <paramref name="key"/> is null.</exception>
		/// <exception cref="ArgumentException">Will be throw if <paramref name="region"/> is empty.</exception>
		/// <exception cref="ArgumentNullException">Will be throw if <paramref name="region"/> is null.</exception>
		void Put ( string key , object value , TimeSpan timeout , string region , string[] tags );

		/// <summary>
		/// Return a set of cache objects with only one round-trip
		/// </summary>
		/// <param name="keys">All the cache key.</param>
		/// <param name="region">The cache region.</param>
		/// <returns>A collection of cache objects.</returns>
		/// <exception cref="ArgumentNullException">Will be throw if <paramref name="keys"/> is null.</exception>
		/// <exception cref="ArgumentException">Will be throw if <paramref name="region"/> is empty.</exception>
		/// <exception cref="ArgumentNullException">Will be throw if <paramref name="region"/> is null.</exception>
		IEnumerable <KeyValuePair <string , object>> BulkGet ( IEnumerable <string> keys , string region );

		/// <summary>
		/// Remove all cache objects associated to the specified cache region.
		/// </summary>
		/// <param name="region">Name of the region.</param>
		/// <exception cref="ArgumentException">Will be throw if <paramref name="region"/> is empty.</exception>
		/// <exception cref="ArgumentNullException">Will be throw if <paramref name="region"/> is null.</exception>
		void ClearRegion ( string region );

		/// <summary>
		/// Retrieve the cache object for the specified cache key.
		/// </summary>
		/// <param name="key">The key.</param>
		/// <returns>The cache object</returns>
		/// <exception cref="ArgumentException">Will be throw if <paramref name="key"/> is empty.</exception>
		/// <exception cref="ArgumentNullException">Will be throw if <paramref name="key"/> is null.</exception>
		object Get ( string key );

		/// <summary>
		/// Retrieve the cache object for the specified cache key and specified region.
		/// </summary>
		/// <param name="key">The key.</param>
		/// <param name="region">The region name.</param>
		/// <returns>The cache object</returns>
		/// <exception cref="ArgumentException">Will be throw if <paramref name="key"/> is empty.</exception>
		/// <exception cref="ArgumentNullException">Will be throw if <paramref name="key"/> is null.</exception>
		/// <exception cref="ArgumentException">Will be throw if <paramref name="region"/> is empty.</exception>
		/// <exception cref="ArgumentNullException">Will be throw if <paramref name="region"/> is null.</exception>
		object Get ( string key, string region );

		/// <summary>
		/// Retrieve the cache object for the specified cache key.
		/// </summary>
		/// <param name="key">The key.</param>
		/// <returns>The cache object</returns>
		/// <exception cref="ArgumentException">Will be throw if <paramref name="key"/> is empty.</exception>
		/// <exception cref="ArgumentNullException">Will be throw if <paramref name="key"/> is null.</exception>
		T Get<T> ( string key );

		/// <summary>
		/// Retrieve the cache object for the specified cache key and specified region.
		/// </summary>
		/// <param name="key">The key.</param>
		/// <param name="region">The region name.</param>
		/// <returns>The cache object</returns>
		/// <exception cref="ArgumentException">Will be throw if <paramref name="key"/> is empty.</exception>
		/// <exception cref="ArgumentNullException">Will be throw if <paramref name="key"/> is null.</exception>
		/// <exception cref="ArgumentException">Will be throw if <paramref name="region"/> is empty.</exception>
		/// <exception cref="ArgumentNullException">Will be throw if <paramref name="region"/> is null.</exception>
		T Get<T> ( string key, string region );

		/// <summary>
		/// Retrieve all cache object with the specified tag and the specified region.
		/// </summary>
		/// <param name="tag">The tags name.</param>
		/// <param name="region">The region name.</param>
		/// <returns>A set of cache object.</returns>
		/// <exception cref="ArgumentException">Will be throw if <paramref name="tag"/> is empty.</exception>
		/// <exception cref="ArgumentNullException">Will be throw if <paramref name="tag"/> is null.</exception>
		/// <exception cref="ArgumentException">Will be throw if <paramref name="region"/> is empty.</exception>
		/// <exception cref="ArgumentNullException">Will be throw if <paramref name="region"/> is null.</exception>
		IEnumerable <KeyValuePair <string , object>> GetObjectsByTag ( string tag , string region );

		/// <summary>
		/// Returns a list of objects that have tags matching all of the tags provided in the parameter of this method.
		/// </summary>
		/// <param name="tags">The tags name.</param>
		/// <param name="region">The region name.</param>
		/// <returns>A set of cache object.</returns>
		/// <exception cref="ArgumentNullException">Will be throw if <paramref name="tags"/> is null.</exception>
		/// <exception cref="ArgumentException">Will be throw if <paramref name="region"/> is empty.</exception>
		/// <exception cref="ArgumentNullException">Will be throw if <paramref name="region"/> is null.</exception>
		IEnumerable <KeyValuePair <string , object>> GetObjectsByAllTags ( string[] tags , string region );
		
		/// <summary>
		/// Returns a list of objects that have tags matching any of the tags provided in the parameter of this method.
		/// </summary>
		/// <param name="tags">The tags.</param>
		/// <param name="region">The region.</param>
		/// <returns>A set of cache object.</returns>
		/// <exception cref="ArgumentNullException">Will be throw if <paramref name="tags"/> is null.</exception>
		/// <exception cref="ArgumentException">Will be throw if <paramref name="region"/> is empty.</exception>
		/// <exception cref="ArgumentNullException">Will be throw if <paramref name="region"/> is null.</exception>
		IEnumerable <KeyValuePair <string , object>> GetObjectsByAnyTags ( string[] tags , string region );

		/// <summary>
		/// Returns a list of all objects in a region. This method is useful when you do not know all the tags used in the region.
		/// </summary>
		/// <param name="region">The region name.</param>
		/// <returns>A set of cache object.</returns>
		/// <exception cref="ArgumentException">Will be throw if <paramref name="region"/> is empty.</exception>
		/// <exception cref="ArgumentNullException">Will be throw if <paramref name="region"/> is null.</exception>
		IEnumerable <KeyValuePair <string , object>> GetObjectsInRegion ( string region );

		/// <summary>
		/// Remove a cache object with the specified key from the cache repository.
		/// </summary>
		/// <param name="key">The key.</param>
		/// <exception cref="ArgumentException">Will be throw if <paramref name="key"/> is empty.</exception>
		/// <exception cref="ArgumentNullException">Will be throw if <paramref name="key"/> is null.</exception>
		void Remove ( string key );

		/// <summary>
		/// Remove a cache object with the specified key and the specified region from the cache repository.
		/// </summary>
		/// <param name="key">The key.</param>
		/// <param name="region">The region.</param>
		/// <exception cref="ArgumentException">Will be throw if <paramref name="key"/> is empty.</exception>
		/// <exception cref="ArgumentNullException">Will be throw if <paramref name="key"/> is null.</exception>
		/// <exception cref="ArgumentException">Will be throw if <paramref name="region"/> is empty.</exception>
		/// <exception cref="ArgumentNullException">Will be throw if <paramref name="region"/> is null.</exception>
		void Remove ( string key , string region);
	}
}